package com.swak.consistency.tcc.role.impls;

import com.swak.consistency.core.aspect.ConsistencyProceeding;
import com.swak.consistency.core.invoke.Invocation;
import com.swak.consistency.core.logger.ConsistencyLogger;
import com.swak.consistency.tcc.context.Phase;
import com.swak.consistency.tcc.context.TccContext;
import com.swak.consistency.tcc.context.TransLog;
import com.swak.consistency.tcc.context.TransParticipant;
import com.swak.consistency.tcc.role.AbstractTransRoler;

/**
 * 事务传输： 发起远程调用时使用； 接口中注解事务注解
 * 
 * @author DELL
 */
public class TransTransmiter extends AbstractTransRoler {

	@Override
	public Object doHandle(TccContext context) {

		// 准备阶段
		if (context.getPhase() == Phase.READY) {

			// 开启分支事务
			this.openBranchTrans(context);
		}

		// 执行业务代码
		Object result = this.doPrepare(context);

		// 返回结果
		return result;
	}

	/**
	 * 传递数据，主要执行：远程调用
	 */
	@Override
	protected Object doPrepare(TccContext context) {
		Throwable error = null;
		Object result = null;
		try {
			result = context.getProceeding().proceed();
		} catch (Throwable e) {
			error = e;
		}

		// 抛出异常
		if (error != null) {
			return this.throwConsistencyException(error);
		}

		// 返回结果
		return result;
	}

	/**
	 * 加入事务
	 * 
	 * @param context
	 */
	@Override
	protected TransParticipant openBranchTrans(TccContext context) {
		
		ConsistencyLogger.debug(context, "开启分支事务");

		TransLog trans = context.getTrans();
		ConsistencyProceeding proceeding = context.getProceeding();

		// 添加事务参数者
		Invocation confirmInvocation = invoker.createInvocation(proceeding, null);
		Invocation cancelInvocation = invoker.createInvocation(proceeding, null);

		TransParticipant participant = new TransParticipant();
		participant.setConfirm(confirmInvocation);
		participant.setCancel(cancelInvocation);
		participant.setExecuted(true);
		trans.addParticipant(participant);

		// 保存事务 -- 事务不成功直接抛出异常
		transLogStorage.updateParticipants(trans);

		return participant;
	}
}